package everyday;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

/**
 * @author 兴趣使然黄小黄
 * @version 1.0
 * @date 2023/6/23 19:02
 * 18. 四数之和
 * https://leetcode.cn/problems/4sum/
 */
public class Solution18 {

    // 排序 + 双指针
    public List<List<Integer>> fourSum(int[] nums, int target) {
        int n = nums.length;
        if (n < 4) {
            return new ArrayList<>();
        }
        List<List<Integer>> ret = new ArrayList<>();  // 存储结果
        Arrays.sort(nums);  // 先将数组排序
        // 计算四数之和 a + b + c + d == target
        // 先固定 a
        for (int i = 0; i <= n - 4; ++i) {
            // 去重
            if (i > 0 && nums[i] == nums[i - 1]) {
                continue;
            }
            // 固定 b
            for (int j = i + 1; j <= n - 3; ++j) {
                // 去重
                if (j > i + 1 && nums[j] == nums[j - 1]) {
                    continue;
                }
                long curTarget = (long) target - nums[i] - nums[j];  // 更新目标值
                int left = j + 1, right = n - 1;  // 双指针
                // 检索过程
                while (left < right) {
                    long curSum = nums[left] + nums[right];
                    if (curSum > curTarget) {
                        --right;
                    } else if (curSum < curTarget) {
                        ++left;
                    } else {
                        // 查找到结果则存储起来
                        ret.add(Arrays.asList(nums[i], nums[j], nums[left], nums[right]));
                        ++left;
                        --right;
                        // 去重
                        while (left < right && nums[left] == nums[left - 1]) {
                            ++left;
                        }
                        while (left < right && nums[right] == nums[right + 1]) {
                            --right;
                        }
                    }
                }
            }
        }
        // 返回结果
        return ret;
    }
}
